﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.Core.FlowEngine.Internal
 * 唯一标识：4160822d-39c1-4c9a-a25a-33578aef02b1
 * 文件名：VampirewalFlowNodeOption
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2023/10/27 17:35:32
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

namespace Vampirewal.Core.FlowEngine;

/// <summary>
/// 流程引擎节点配置器
/// </summary>
internal class VampirewalFlowNodeOption : IVampirewalFlowNodeOption
{
    public VampirewalFlowNodeOption(Flow flowInfo)
    {
        Units = new List<FlowUnit>();
        Links = new List<FlowLink>();
        FlowInfo = flowInfo;
    }

    public Flow FlowInfo { get; set; }

    public List<FlowUnit> Units { get; set; }

    public List<FlowLink> Links { get; set; }

    /// <summary>
    /// 设置开始节点
    /// </summary>
    /// <returns></returns>
    public IVampirewalFlowNodeOption SetStartNode(ExcutionModeType mode)
    {
        FlowUnit unit = new FlowUnit()
        {
            DtlId = Guid.NewGuid().ToString(),
            BillId = FlowInfo.BillId,
            IsFirst = true,
            UnitType = FlowUnitType.Start,
            UnitIndex = 0,
            Description = "开始节点",
            UnitName = "开始",
            ExcutionMode = mode
        };

        Units.Add(unit);

        return this;
    }

    /// <summary>
    /// 设置普通节点
    /// </summary>
    /// <param name="UnitIndex">节点序号</param>
    /// <param name="UnitName">节点名称</param>
    /// <param name="Description">节点描述</param>
    /// <param name="mode">节点执行方式</param>
    /// <param name="SetLink">配置连线</param>
    /// <returns></returns>
    public IVampirewalFlowNodeOption SetNormalNode(int UnitIndex, string UnitName, string Description, ExcutionModeType mode, Action<IVampirewalFlowLinkOption> SetLink)
    {
        var startnode = Units.FirstOrDefault(f => f.UnitIndex == 0);

        FlowUnit unit = new FlowUnit()
        {
            DtlId = Guid.NewGuid().ToString(),
            IsFirst = false,
            UnitType = FlowUnitType.Normal,
            UnitIndex = UnitIndex,
            Description = Description,
            UnitName = UnitName,
            RejectUnitId = startnode.DtlId,
            ExcutionMode = mode
        };

        Units.Add(unit);

        VampirewalFlowLinkOption linkOption = new VampirewalFlowLinkOption(Units, FlowInfo);

        SetLink.Invoke(linkOption);

        linkOption.Link.NextUnitId = unit.DtlId;

        Links.Add(linkOption.Link);

        return this;
    }

    /// <summary>
    /// 设置普通节点
    /// </summary>
    /// <param name="UnitIndex">节点序号</param>
    /// <param name="UnitName">节点名称</param>
    /// <param name="Description">节点描述</param>
    /// <param name="mode">节点执行方式</param>
    /// <param name="RejectUnitIndex">驳回节点</param>
    /// <param name="SetLink">配置连线</param>
    /// <returns></returns>
    public IVampirewalFlowNodeOption SetNormalNode(int UnitIndex, string UnitName, string Description, ExcutionModeType mode, int RejectUnitIndex, Action<IVampirewalFlowLinkOption> SetLink)
    {
        var rejectnode = Units.FirstOrDefault(f => f.UnitIndex == RejectUnitIndex);

        FlowUnit unit = new FlowUnit()
        {
            DtlId = Guid.NewGuid().ToString(),
            IsFirst = false,
            UnitType = FlowUnitType.Normal,
            UnitIndex = UnitIndex,
            Description = Description,
            UnitName = UnitName,
            RejectUnitId = rejectnode.DtlId,
            ExcutionMode = mode
        };

        Units.Add(unit);

        VampirewalFlowLinkOption linkOption = new VampirewalFlowLinkOption(Units, FlowInfo);

        SetLink.Invoke(linkOption);

        linkOption.Link.NextUnitId = unit.DtlId;

        Links.Add(linkOption.Link);

        return this;
    }

    /// <summary>
    /// 设置结束节点
    /// </summary>
    /// <param name="UnitIndex">节点序号</param>
    /// <param name="SetLink">配置连线</param>
    /// <returns></returns>
    public void SetEndNode(int UnitIndex, Action<IVampirewalFlowLinkOption> SetLink)
    {
        FlowUnit unit = new FlowUnit()
        {
            DtlId = Guid.NewGuid().ToString(),
            IsFirst = false,
            UnitType = FlowUnitType.End,
            UnitIndex = UnitIndex,
            Description = "结束节点",
            UnitName = "结束节点",
        };

        Units.Add(unit);

        VampirewalFlowLinkOption linkOption = new VampirewalFlowLinkOption(Units, FlowInfo);

        SetLink.Invoke(linkOption);

        linkOption.Link.NextUnitId = unit.DtlId;

        Links.Add(linkOption.Link);
    }
}